//
//  HQL11_1ViewController.h
//  CoreAnimationDemo
//
//  Created by Qilin Hu on 2019/9/26.
//  Copyright © 2019 Tonintech. All rights reserved.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

/// 使用 NSTimer 实现弹性球动画
@interface HQL11_1ViewController : UIViewController

@end

NS_ASSUME_NONNULL_END

/*
 # 定时帧
 
 ## NSTimer
 
 在时钟示例中，我们用了 NSTimer 来对钟表的指针做定时动画，一秒钟更新一次，但是如果我们把频率调整成一秒钟更新 60 次的话，原理是完全相同的。
 
 使用 NSTimer 实现弹性球动画和基于关键帧例子的代码一样很多，但是如果想一次性在屏幕上对很多东西做动画，很明显就会有很多问题。
 
 NSTimer 并不是最佳方案，为了理解这点，我们需要确切地知道 NSTimer 是如何工作的。iOS 上的每个线程都管理了一个 NSRunloop，字面上看就是通过一个循环来完成一些任务列表。但是对主线程，这些任务包含如下几项：
 * 处理触摸事件
 * 发送和接受网络数据包
 * 执行使用 gcd 的代码
 * 处理计时器行为
 * 屏幕重绘
 
 当你设置一个 NSTimer，他会被插入到当前任务列表中，然后直到指定时间过去之后才会被执行。
 但是何时启动定时器并没有一个时间上限，而且它只会在列表中上一个任务完成之后开始执行。
 这通常会导致有几毫秒的延迟，但是如果上一个任务过了很久才完成就会导致延迟很长一段时间。
 
 屏幕重绘的频率是一秒钟六十次，但是和定时器行为一样，如果列表中上一个执行了很长时间，它也会延迟。
 这些延迟都是一个随机值，于是就不能保证定时器精准地一秒钟执行六十次。
 有时候发生在屏幕重绘之后，这就会使得更新屏幕会有个延迟，看起来就是动画卡壳了。
 有时候定时器会在屏幕更新的时候执行两次，于是动画看起来就跳动了。
 
 我们可以通过一些途径来优化：
 * 我们可以用 CADisplayLink 让更新频率严格控制在每次屏幕刷新之后。
 * 基于真实帧的持续时间而不是假设的更新频率来做动画。
 * 调整动画计时器的 run loop 模式，这样就不会被别的事件干扰。
 
 */
